package com.custom.controls
{
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	import mx.controls.List;
	import mx.core.ScrollPolicy;
	import mx.effects.Tween;
	import mx.events.ScrollEvent;
	import mx.events.ScrollEventDetail;
	import mx.effects.easing.*


	/**
	 *  List that uses smooth scrolling
	 */
	public class SmoothScrollingList extends List
	{
		
		private var fudge:Number;
		
		public function SmoothScrollingList()
		{
			super();
			offscreenExtraRowsOrColumns = 2;
		}

		/**
		 * Override the mouseWheelHandler so if the verticalScrollPolicy is "off"
		 * we use the MouseEvent.delta value to manually update the List control
		 * scroll position when there is no ScrollBar.
		 *
		 * */
		override protected function mouseWheelHandler(event:MouseEvent):void
		{
			if(verticalScrollPolicy == ScrollPolicy.OFF && maxVerticalScrollPosition != 0){
				var len:Number = dataProvider.length;
				var delta:Number = Number(event.delta);
				var pos:Number = verticalScrollPosition;
				var newpos:Number = verticalScrollPosition;

				if(delta < 0){
					delta = Math.abs(delta);
					if(pos + delta >= maxVerticalScrollPosition) {
						newpos = maxVerticalScrollPosition;
					} else {
						newpos = pos + Math.abs(delta); 
					}
				} else {
					if( ((pos - delta) <= 0 ) || pos == 0){
						newpos = 0;
					} else {
						newpos = pos - delta;
					}
				}
				
				verticalScrollPosition = newpos;
			} 
			
			super.mouseWheelHandler(event);
		}
		
		private function tweenScroll (t:Number, b:Number, c:Number, d:Number):Number 
		{
		  	var ts:Number=(t/=d)*t;
		  	var tc:Number=ts*t;
		  	return b+c*(1*tc*ts + -5*ts*ts + 10*tc + -10*ts + 5*t);
		}

		override protected function configureScrollBars():void
		{
			super.configureScrollBars();
			if (verticalScrollBar)
				verticalScrollBar.lineScrollSize = .125;  // should be inverse power of 2
		}

	
		override public function get verticalScrollPosition():Number
		{
			if (!isNaN(fudge))
			{
				var vsp:Number = super.verticalScrollPosition + fudge;
				fudge = NaN;
				return vsp;
			}
			return Math.floor(super.verticalScrollPosition);
		}

		override protected function scrollHandler(event:Event):void
		{
			// going backward is trickier.  When you cross from, for instance 2.1 to 1.9, you need to convince
			// the superclass that it is going from 2 to 1 so the delta is -1 and not -.2.
			// we do this by adding a fudge factor to the first return from verticalScrollPosition
			// which is used by the superclass logic.
			var last:Number = super.verticalScrollPosition;
			var vsp:Number = verticalScrollBar.scrollPosition;
			if (vsp < last)
			{
				if (last != Math.floor(last) || vsp != Math.floor(vsp))
				{
					if (Math.floor(vsp) < Math.floor(last))
					{
						fudge = Math.floor(last) - Math.floor(verticalScrollBar.scrollPosition);
						trace(last.toFixed(2), vsp.toFixed(2), fudge);
					}
				}
			}

			super.scrollHandler(event);
			var pos:Number = super.verticalScrollPosition;
			// if we get a THUMB_TRACK, then we need to calculate the position
			// because it gets rounded to an int by the ScrollThumb code, and 
			// we want fractional values.
			if (event is ScrollEvent)
			{
				var se:ScrollEvent = ScrollEvent(event);
				if (se.detail == ScrollEventDetail.THUMB_TRACK)
				{
					if (verticalScrollBar.numChildren == 4)
					{
						var downArrow:DisplayObject = verticalScrollBar.getChildAt(3);
						var thumb:DisplayObject = verticalScrollBar.getChildAt(2);
						pos = (thumb.y - downArrow.height) / (downArrow.y - thumb.height - downArrow.height) * maxVerticalScrollPosition;
						// round to nearest lineScrollSize;
						pos /= verticalScrollBar.lineScrollSize;
						pos = Math.round(pos);
						pos *= verticalScrollBar.lineScrollSize;
						//trace("faked", pos);
					}
				}
			}
			var fraction:Number = pos - verticalScrollPosition;
			fraction *= rowHeight;
			//trace("was", listContent.y.toFixed(2));
			listContent.move(listContent.x, viewMetrics.top + listContent.topOffset - fraction);
		//trace("now", listContent.y.toFixed(2), fraction.toFixed(2), listItems[0][0].data.lastName);
		}

	}

}
